import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKeys;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UcarViewInjectGenorator extends AnAction {

    private List<Map<String, String>> xmlList = new ArrayList<>();

    @Override
    public void actionPerformed(AnActionEvent e) {
        Editor editor = e.getData(DataKeys.EDITOR);

        if (editor != null) {
            //得到编辑器的光标类
            CaretModel caret = editor.getCaretModel();
//            Messages.showMessageDialog("测试**" + caret, "弹框标题", Messages.getInformationIcon());

            PsiFile psiFile = e.getData(DataKeys.PSI_FILE);
            int offset = caret.getOffset();
            PsiElement elementAt = psiFile.findElementAt(offset);
            if ("".equals(elementAt.getText()) || ")".equals(elementAt.getText())) {
                elementAt = psiFile.findElementAt(offset - 1);
            }
            if (elementAt.getParent() != null && "R.layout".equals(elementAt.getParent().getFirstChild().getText())) {
                String fileName = String.format("%s.xml", elementAt.getText());


                Module moduleForPsiElement = ModuleUtil.findModuleForPsiElement(elementAt);
                GlobalSearchScope searchScope = GlobalSearchScope.moduleScope(moduleForPsiElement);
                Project project = e.getData(DataKeys.PROJECT);
                PsiFile[] psiFiles = FilenameIndex.getFilesByName(project, fileName, searchScope);

                xmlList.clear();
                if (psiFiles.length > 0) {
                    PsiFile pFile = psiFiles[0];
                    pFile.accept(new XmlRecursiveElementVisitor(){
                        @Override
                        public void visitXmlTag(XmlTag tag) {
                            super.visitXmlTag(tag);
                            XmlAttribute attributeId = tag.getAttribute("android:id");
                            String layoutName = tag.getName();
                            if (attributeId != null) {
                                String idValue = attributeId.getValue();
                                String[] split = idValue.split("/");
                                String id = split[1].trim();
                                //先处理include标签
                                if("include".equals(layoutName)){
                                    XmlAttribute attributeLayout= tag.getAttribute("layout");
                                    if(attributeLayout != null){
                                        String name = attributeLayout.getValue().split("/")[1].trim();
                                        PsiFile[] psiFiles = FilenameIndex.getFilesByName(project, name + ".xml", searchScope);
                                        if(psiFiles.length > 0){
                                            psiFiles[0].accept(new XmlRecursiveElementVisitor(){
                                                @Override
                                                public void visitXmlTag(XmlTag tag) {
                                                    super.visitXmlTag(tag);
                                                    XmlAttribute firstLayout = tag.getAttribute("xmlns:android");
                                                    if(firstLayout != null){
                                                        String layoutName = tag.getName();
                                                        Map<String, String> map = new HashMap<>();
                                                        map.put("id", id);
                                                        map.put("name", layoutName);
                                                        xmlList.add(map);
                                                    }
                                                }
                                            });
                                        }
                                    }
                                }else{
                                    if (idValue != null && idValue.startsWith("@+id/")) {
                                        Map<String, String> map = new HashMap<>();
                                        map.put("id", id);
                                        map.put("name", layoutName);
                                        xmlList.add(map);
                                    }
                                }
                            }
                        }
                    });

                    //将id生成至页面
                    GlobalSearchScope globalSearchScope = GlobalSearchScope.fileScope(psiFile);
                    String fullName = psiFile.getName();
                    String className = fullName.split("\\.")[0];
                    PsiClass psiClass = PsiShortNamesCache.getInstance(psiFile.getProject()).getClassesByName(className, globalSearchScope)[0];


                    PsiElementFactory psiElementFactory = PsiElementFactory.SERVICE.getInstance(elementAt.getProject());
                    new WriteCommandAction(psiFile.getProject(), psiFile) {

                        @Override
                        protected void run(@NotNull Result result) throws Throwable {

                            GlobalSearchScope scope = GlobalSearchScope.allScope(project);
                            PsiClass activityClass = JavaPsiFacade.getInstance(project).findClass(
                                    "android.app.Activity", scope);
                            PsiClass fragmentClass = JavaPsiFacade.getInstance(project).findClass(
                                    "android.app.Fragment", scope);
                            PsiClass supportFragmentClass = JavaPsiFacade.getInstance(project).findClass(
                                    "android.support.v4.app.Fragment", scope);

                            String methodFront = "private void findViews(){";
                            String findFront = "";
                            if (activityClass != null && psiClass.isInheritor(activityClass, false)) { //当前类为activity
                                methodFront = "private void findViews(){";
                                findFront = "";
                            }else if (fragmentClass != null && psiClass.isInheritor(fragmentClass, false)
                                    || supportFragmentClass != null && psiClass.isInheritor(supportFragmentClass, false)) { //当前类为fragment
                                methodFront = "private void findViews(View view){";
                                findFront = "view.";
                            }

                            StringBuilder method = new StringBuilder();
                            method.append(methodFront);
                            for (Map<String, String> eachMap : xmlList) {
                                String id = eachMap.get("id");
                                String name = eachMap.get("name");

//                                if (psiClass.findFieldByName(id, false) == null) {//没创建过该变量
                                    PsiField fieldElement = psiElementFactory.createFieldFromText(
                                            "@ViewInject(" +
                                                    "\"" +
                                                    id +
                                                    "\")" +
                                                    "private"
                                                    + " "
                                                    + name
                                                    + " "
                                                    + id
                                                    + ";"
                                            , psiClass);
                                    psiClass.add(fieldElement);

//                                }


                                method.append(id)
                                        .append(" = ")
                                        .append("(")
                                        .append(name)
                                        .append(")")
                                        .append(findFront + "findViewById(")
                                        .append("R.id.")
                                        .append(id)
                                        .append(");");

                            }

                            method.append("}");
                            PsiMethod methodElement = psiElementFactory.createMethodFromText(method.toString(), psiClass);
//                            psiClass.add(methodElement);

                        }
                    }.execute();



//                    Messages.showMessageDialog("文件<" + fileName + ">查找成功，共" + psiFiles.length + "个" + xmlList.size(), "Ucar ViewInject Genorator", Messages.getInformationIcon());
                } else {
                    Messages.showMessageDialog("未找到此名称文件", "Ucar ViewInject Genorator", Messages.getInformationIcon());
                }


            } else {
                Messages.showMessageDialog("布局文件查找失败，请将光标置于布局文件名称上", "Ucar ViewInject Genorator", Messages.getInformationIcon());
            }
        }
    }
}

